package com.mod.enemies {
	
	import com.calefk.core.EntitySimple;
	import com.calefk.core.Project;
	import com.calefk.util.IntUtil;
	import com.mod.reanimator.BaseVillager;
	import com.mod.reanimator.Player;
	import flash.display.MovieClip;
	import com.mod.Global;
	import com.calefk.modules.math.Vector2D;
	import com.calefk.util.Generic;
	
	public class Enemy extends EntitySimple {
		
		protected var mLife:int = 100;
		protected var mTotalLife:int = 100;
		
		private var mIsDie:Boolean;
		
		// gameplay
		protected var mMaxSpeed:Number = 50;
		protected var mSpeedVect:Vector2D = null;
		protected var mMyCollision:MovieClip = null;
		
		protected var mObjectiveType:int = 0;
		
		// attack wait
		protected var mAttackWaitTime:int = 1000;
		private var mAttackWaitCounter:int = 0;
		private var waitingAttack:Boolean = false;
		
		// angle rotation
		protected var mAngleChange:Number = 5;
		protected var mAngleCounter:Number = 0;
		protected var mMaxAngleChange:Number = 90;
		
		// Enemy states
		protected var mState:int = 0;
		
		public static const ST_STANDBY:int = 0;
		public static const ST_MOVING:int = 1;
		public static const ST_FIGHTING:int = 2;
		public static const ST_OVER:int = 3;
		
		public static const VILLAGE_COL:String = "collision_mc";
		public static const PLAYER_COL:String = "collision_mc";
		public static const ENEMY_COL:String = "mc_collision";
		
		public static const AT_VICTIM:int = 0;
		public static const AT_PLAYER:int = 1;
		public static const AT_BASE:int = 2;
		
		public static const WIDTH_HEALTHBAR:int = 40;
		public var DAMAGE_PTS:int = -20;
		
		// Victims
		public var mVictim:BaseVillager = null;
		public var mPlayerRef:Player = null;
		public var mHeart:MovieClip = null;
		
		// gets
		public function get state():int { return mState; }
		public function get life():int { return mLife; }
		public function get collision():MovieClip { return mMyCollision; }
		
		//HealthBar
		private var healthBar:MovieClip;
		
		public function Enemy(canvas:MovieClip, nameClip:String = null, 
				px:Number=0, py:Number=0, project:Project=null) {
			super(canvas, nameClip, px, py, project);
			mLife = mTotalLife;
			healthBar = Global.project.getMovie("barBad");
			clip.addChild(healthBar); healthBar.y = -clip.height / 2; healthBar.x = -clip.width / 2+15;
			mClip.endDie = endDie;
			mClip.endAttack = endAttack;
			mState = ST_STANDBY;
			mClip.gotoAndStop("moving");
		}
		
		// DIE STUFF
		public function onReceiveDamage(mount:int,guard:BaseVillager):void {
			if (mIsDie) return;
			mLife += mount;
			healthBar.filler_mc.x = ( (mLife/mTotalLife) * WIDTH_HEALTHBAR );
			if (mLife <= 0) {
				mIsDie = true;
				onAnimationDie();
			}
			if (guard) {
				mVictim = guard;
			}
		}
		private function onAnimationDie():void {
			Global.playSound("snd_death", 1, 1);
			mClip.gotoAndStop("dying");
			mState = ST_OVER;
		}
		private function endDie():void {
			toClean = true;
		}
		
		// VICTIM FUNCTIONS
		protected function beginMovement():void {
			if (Global.engine.player) {
				mPlayerRef = Global.engine.player;
			}
			if (mClip && mClip[""+ENEMY_COL])  {
				mMyCollision = mClip[""+ENEMY_COL]
			}
			if (Global.engine.world.hearth) {
				mHeart = Global.engine.world.hearth;
			}
			mState = ST_MOVING;
		}
		//
		protected function findVictim(dt:int):void {
			var potentialVictims:Array = Global.engine.world.arrayVillagers;
			var closeDude:BaseVillager = null;
			var bestVictim:BaseVillager = null;
			var minDist:Number = 1000;
			for (var v:int = 0; v < potentialVictims.length; v++) {
				//find closest villager
				closeDude = potentialVictims[v];
				if (!closeDude.toClean && 
					((closeDude.currentState == BaseVillager.MOVING) || (closeDude.currentState == BaseVillager.FIGHTING))) {
					if (getDistanceToVictim(closeDude) < minDist) {
						minDist = getDistanceToVictim(closeDude);
						bestVictim = closeDude;
					}
				}
			}
			mVictim = bestVictim;
		}
		private function getDistanceToVictim(dude:BaseVillager):Number {
			var distVector:Vector2D = new Vector2D(dude.x - this.x, dude.y - this.y);
			return distVector.length();
		}
		
		// COLLISIONS
		// revisa si hay colision con la victima actual
		protected function checkCollisionWVictim():Boolean {
			if (mVictim && mVictim.clip && mVictim.clip["" + VILLAGE_COL] 
				&& mMyCollision) {
				if (mMyCollision.hitTestObject(mVictim.clip["" + VILLAGE_COL])) {
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}
		protected function checkCollisionWPlayer():Boolean {
			if (mPlayerRef && mPlayerRef.clip && mPlayerRef.clip[""+PLAYER_COL] && mMyCollision) {
				if (mMyCollision.hitTestObject(mPlayerRef.clip[""+PLAYER_COL])) {
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}
		protected function checkCollisionWHeart():Boolean {
			if (mHeart && mMyCollision) {
				if (mMyCollision.hitTestObject(mHeart)) {
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}
		
		// FIGHT
		protected function updateFighting(dt:int):void {
			// busca victima
			if (waitingAttack) {
				mAttackWaitCounter += dt;
				if (mAttackWaitTime < mAttackWaitCounter) {
					waitingAttack = false;
					mAttackWaitCounter = 0;
				} else {
					return;
				}
			}
			if ((mObjectiveType == AT_VICTIM) && (!mVictim)) {
				mObjectiveType = AT_PLAYER;
			}
			switch (mObjectiveType) {
				case AT_VICTIM:
					if (mVictim) {
						if (!checkCollisionWVictim()) {
							mState = ST_MOVING;
						} else {
							// attack victim
							attackVictim();
							waitingAttack = true;
						}
					}
					break;
				case AT_PLAYER:
					if (mPlayerRef) {
						if (!checkCollisionWPlayer()) {
							mState = ST_MOVING;
						} else {
							//attack player
							attackPlayer();
							waitingAttack = true;
						}
					}
					break;
				case AT_BASE:
					if (mHeart) {
						if (!checkCollisionWHeart()) {
							mState = ST_MOVING;
						} else {
							//attack player
							attackHeart();
							waitingAttack = true;
						}
					}
					break;
			}
			
		}
		private function endAttack():void {
			if (mClip) {
				mClip.gotoAndStop("moving");
			}
		}
		
		// COMBAT
		private function attackVictim():void {
			if (!mVictim) return;
			mClip.gotoAndStop("attacking");
			//
			Global.playSound("snd_attack_enemy1",1,0.2);
			mVictim.onReceiveDamage(DAMAGE_PTS);
		}
		
		private function attackPlayer():void {
			if (!mPlayerRef) return;
			mClip.gotoAndStop("attacking");
			//
			Global.playSound("snd_attack_enemy1",1,0.2);
			mPlayerRef.onReceiveDamage(DAMAGE_PTS);
		}
		
		private function attackHeart():void {
			if (!mHeart) return;
			mClip.gotoAndStop("attacking");
			//
			Global.playSound("snd_attack_enemy2",1,5);
			Global.engine.heartSkin.onReceiveDamage(DAMAGE_PTS);
		}
		
		// GO AFTER
		protected function goAfterVictim(dt:int):void {
			// chequea si esta lo suficientemente cerca como para atacar
			if (checkCollisionWVictim()) {
				mState = ST_FIGHTING;
			}
			//
			var tomove:Number = (mMaxSpeed * dt) / 1000;
			mSpeedVect = null;
			if (mVictim) {
				//posicion del player
				mSpeedVect = new Vector2D(mVictim.x - this.x, mVictim.y - this.y);
				mSpeedVect.normalize();
				mSpeedVect.scale(tomove);
			} else { return; }
			if (mSpeedVect) {
				var oldX:Number = this.x; var oldY:Number = this.y;
				move(mSpeedVect.x, mSpeedVect.y);
				//chequeo con la base central
				var baseColl:MovieClip = Global.engine.world.hearth;
				if (mMyCollision){
					if (mMyCollision.hitTestObject(baseColl)) {
						this.x = oldX;
						this.y = oldY;
						//buscar una nueva direccion
						for (mAngleCounter = 0; mAngleCounter <= mMaxAngleChange; mAngleCounter += mAngleChange ) {
							// decide si debe rotar positiva o negativamente
							//
							Vector2D.rotateSameVector(mSpeedVect, mAngleChange);
							move(mSpeedVect.x, mSpeedVect.y);
							if (mMyCollision.hitTestObject(baseColl)) {
								// intentar de nuevo
								this.x = oldX;
								this.y = oldY;
							} else {
								break;
							}
						}
						//si acaba el for y aun no mueve se queda quieto
					}
				}
				//
			}
		}
		//
		protected function goAfterPlayer(dt:int):void {
			// chequea si esta lo suficientemente cerca como para atacar
			if (checkCollisionWPlayer()) {
				mState = ST_FIGHTING;
			}
			//
			var tomove:Number = (mMaxSpeed * dt) / 1000;
			mSpeedVect = null;
			if (mPlayerRef) {
				//posicion del player
				mSpeedVect = new Vector2D(mPlayerRef.x - this.x, mPlayerRef.y - this.y);
				mSpeedVect.normalize();
				mSpeedVect.scale(tomove);
			} else { return; }
			if (mSpeedVect) {
				var oldX:Number = this.x; var oldY:Number = this.y;
				move(mSpeedVect.x, mSpeedVect.y);
				//chequeo con la base central
				var baseColl:MovieClip = Global.engine.world.hearth;
				if (mMyCollision){
					if (mMyCollision.hitTestObject(baseColl)) {
						this.x = oldX;
						this.y = oldY;
						//buscar una nueva direccion
						for (mAngleCounter = 0; mAngleCounter <= mMaxAngleChange; mAngleCounter += mAngleChange ) {
							// decide si debe rotar positiva o negativamente
							//
							Vector2D.rotateSameVector(mSpeedVect, mAngleChange);
							move(mSpeedVect.x, mSpeedVect.y);
							if (mMyCollision.hitTestObject(baseColl)) {
								// intentar de nuevo
								this.x = oldX;
								this.y = oldY;
							} else {
								break;
							}
						}
						//si acaba el for y aun no mueve se queda quieto
					}
				}
				//
			}
		}
		//
		protected function goAfterHeart(dt:int):void {
			// chequea si esta lo suficientemente cerca como para atacar
			if (checkCollisionWHeart()) {
				mState = ST_FIGHTING;
			}
			//
			var tomove:Number = (mMaxSpeed * dt) / 1000;
			mSpeedVect = null;
			if (mHeart) {
				//posicion del player
				mSpeedVect = new Vector2D(mHeart.x - this.x, mHeart.y - this.y);
				mSpeedVect.normalize();
				mSpeedVect.scale(tomove);
			} else { return; }
			if (mSpeedVect) {
				var oldX:Number = this.x; var oldY:Number = this.y;
				move(mSpeedVect.x, mSpeedVect.y);
				//chequeo con la base central
				if (mMyCollision){
					if (mMyCollision.hitTestObject(mHeart)) {
						mState = ST_FIGHTING;
					}
				}
				//
			}
		}
		
		// UPDATE
		override public function update(dt:int):void {
			if ((mVictim && mVictim.toClean) ||
				(mVictim && (mVictim.currentState != BaseVillager.MOVING && 
				mVictim.currentState!=BaseVillager.FIGHTING)) ) {
				mVictim = null;
			}
			super.update(dt);
		}
		
		// CLEAN
		override public function clean():void {
			super.clean();
		}
		
	}

}